package com.contory.ssn_lgnd.framework.gl;

import java.io.IOException;
import java.io.InputStream;

import javax.microedition.khronos.opengles.GL10;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.opengl.GLES20;
import android.opengl.GLUtils;

import com.contory.ssn_lgnd.framework.FileIO;
import com.contory.ssn_lgnd.framework.impl.GLGame;

public class Texture implements TexturePtr{
	FileIO fileIO;
	String fileName;
	int textureId;
	int minFilter;
	int magFilter;
	public int width;
	public int height;
	boolean mipmapped;
	
	public Texture(GLGame glGame, String fileName) {
		this(glGame, fileName, false);
	}

	public Texture(GLGame glGame, String fileName, boolean mipmapped) {
		this.fileIO = glGame.getFileIO();
		this.fileName = fileName;
		this.mipmapped = mipmapped;
		load();
	}
	
	public void load() {
		int[] textureIds = new int[1];
		GLES20.glGenTextures(1, textureIds, 0);
		textureId = textureIds[0];
		textureIds= null;
		InputStream in = null;
		try {
			in = fileIO.readAsset(fileName);
			Bitmap bitmap = BitmapFactory.decodeStream(in);
			if (mipmapped) {
				createMipmaps(bitmap);
			} else {
				GLES20.glBindTexture ( GLES20.GL_TEXTURE_2D, textureId );
				GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
				setFilters(GLES20.GL_NEAREST, GLES20.GL_NEAREST);
				GLES20.glBindTexture ( GLES20.GL_TEXTURE_2D, 0 );
				width = bitmap.getWidth();
				height = bitmap.getHeight();
				bitmap.recycle();
			}
		} catch (IOException e) {
			throw new RuntimeException("Couldn't load texture '" + fileName
					+ "'", e);
		} finally {
			if (in != null)
				try {
					in.close();
				} catch (IOException e) {
				}
		}
	}

	private void createMipmaps(Bitmap bitmap) {
		GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
        width = bitmap.getWidth();
		height = bitmap.getHeight();
		setFilters(GLES20.GL_LINEAR_MIPMAP_NEAREST, GLES20.GL_LINEAR);

		int level = 0;
		int newWidth = width;
		int newHeight = height;
		while (true) {
			GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, level, bitmap, 0);
			newWidth = newWidth / 2;
			newHeight = newHeight / 2;
			if (newWidth <= 0)
				break;
			Bitmap newBitmap = Bitmap.createBitmap(newWidth, newHeight,
					bitmap.getConfig());
			Canvas canvas = new Canvas(newBitmap);
			canvas.drawBitmap(bitmap,
					new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()),
					new Rect(0, 0, newWidth, newHeight), null);
			bitmap.recycle();
			bitmap = newBitmap;
			level++;
		}
		
		GLES20.glBindTexture ( GLES20.GL_TEXTURE_2D, 0 );
		bitmap.recycle();
	}

	private void setFilters(int minFilter, int magFilter) {
		this.minFilter = minFilter;
		this.magFilter = magFilter;
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, minFilter);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, magFilter);
	}
	
	public int getTexId(){
		return textureId;
	}

	public void bind(ESShader shader, String texMapName, int activeTexPos) {
		int activeTexPosParam = activeTexPos + GLES20.GL_TEXTURE0;
		GLES20.glActiveTexture(activeTexPosParam);
		GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
		GLES20.glUniform1i(shader.getUniform(texMapName), activeTexPos);
	}

	public void dispose() {
		GLES20.glBindTexture ( GLES20.GL_TEXTURE_2D, textureId );
		int[] textureIds = { textureId };
		GLES20.glDeleteTextures(1, textureIds, 0);
	}
}